home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 2 / AACD 2.iso / AACD / Magazine / GraphicsCards / StormMesa / OpenStep / MesaView / mesadraw.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-12-15  |  9.5 KB  |  357 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <memory.h>
  4. #include "mesadraw.h"
  5. #include "vect3d.h"
  6.  
  7. #define DIM 32
  8. #define MAX_HEIGHT (300/DIM)
  9. #define RADS(x) ((x)/57.29577951)
  10.  
  11. static GLdouble mesh[DIM][DIM][3];
  12. static GLubyte cols[DIM][DIM][3];
  13.  
  14. /*
  15.  * Create a random matrix of heights and colours
  16.  */
  17.  
  18. void make_matrix(void)
  19. {
  20.   int i,j;
  21.  
  22.   for(i=0;i<DIM;i++)
  23.     for(j=0;j<DIM;j++)
  24.      {
  25.        mesh[i][j][0]=((100.0*i)/(DIM-1.0))-50.0;
  26.        mesh[i][j][2]=((100.0*j)/(DIM-1.0))-50.0;
  27.        mesh[i][j][1]=(rand()%MAX_HEIGHT);
  28.        cols[i][j][0]=(mesh[i][j][1]*255)/MAX_HEIGHT;
  29.        cols[i][j][1]=255-cols[i][j][0];
  30.        cols[i][j][2]=0;
  31.      }
  32. }
  33.  
  34. /*
  35.  * Initialise the OpenGL stuff
  36.  */
  37.  
  38. void my_init (float w, float h) 
  39. {
  40.   GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 };
  41.   GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
  42.   GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
  43.   GLfloat light_position[] = { 5.0, 3.0, 9.0, 0.0 };
  44.  
  45.   glMatrixMode (GL_PROJECTION);
  46.   glLoadIdentity ();
  47.   glMatrixMode (GL_MODELVIEW);
  48.   glLoadIdentity ();
  49.  
  50.  
  51.   glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
  52.   glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
  53.   glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
  54.   glLightfv(GL_LIGHT0, GL_POSITION, light_position);
  55.  
  56.   glShadeModel(GL_SMOOTH);
  57.   glEnable(GL_LIGHT0);
  58.   glEnable(GL_LIGHTING);
  59.   glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
  60.   glEnable(GL_COLOR_MATERIAL);
  61.   glEnable(GL_DEPTH_TEST);
  62.  
  63.   glViewport(0,0,w,h);
  64.   glMatrixMode (GL_PROJECTION);
  65.   gluPerspective (60.0, w/h, 1.0, 400.0);
  66. }
  67.  
  68. /*
  69.  * Set the viewpoint
  70.  */
  71.  
  72. void set_viewpoint(float zoomDist, float elevAngle, float spinAngle)
  73. {
  74.     float flat_radius, x, y, z, xl, zl;
  75.     flat_radius=zoomDist*cos(RADS(elevAngle));
  76.     x=0.0-(flat_radius*sin(RADS(spinAngle)));
  77.     xl=50.0*sin(RADS(spinAngle));
  78.     z=flat_radius*cos(RADS(spinAngle));
  79.     zl= -50.0*cos(RADS(spinAngle));
  80.     y=zoomDist*sin(RADS(elevAngle));
  81.  
  82.     glMatrixMode (GL_MODELVIEW);
  83.     glLoadIdentity ();
  84. /*
  85.  * we make a somewhat spurious "up" vector because we know we are 
  86.  * looking at the origin and that it's mapped into the plane of
  87.  * the screen anyway so the percise direction is irrelevent.
  88.  */
  89.     gluLookAt (x, y, z,
  90.                0, 0, 0,
  91.                xl, 50, zl);
  92. }
  93.  
  94. /*
  95.  * Get a normal to a corner of a quad.
  96.  */
  97.  
  98. void get_quad_normal(int x, int z, int cx, int cz, GLdouble n[3])
  99. {
  100.         GLdouble *c1, *c2, *c3, *c4;
  101.         c1 = &mesh[x][z][0];
  102.         c2 = &mesh[x+1][z][0];
  103.         c3 = &mesh[x+1][z+1][0];
  104.         c4 = &mesh[x][z+1][0];
  105.         if((cx==0) && (cz==0))
  106.          return perpnorm(c4,c1,c2,n);
  107.         if((cx==0) && (cz==0))
  108.          return perpnorm(c4,c1,c2,n);
  109.         if((cx==1) && (cz==0))
  110.           return perpnorm(c1,c2,c3,n);
  111.         if((cx==1) && (cz==1))
  112.           return perpnorm(c2,c3,c4,n);
  113.         if((cx==0) && (cz==1))
  114.           return perpnorm(c3,c4,c1,n);
  115. }
  116.  
  117. /*
  118.  * Get a normal to a plane as the average of
  119.  * the normals at the four corners of the quad.
  120.  */
  121.  
  122. void get_plane_normal(int x, int z, GLdouble n[3])
  123. {
  124.    GLdouble total[3]={0,0,0};
  125.    get_quad_normal(x,z,0,0,n);
  126.    add3(total,n,total);
  127.    get_quad_normal(x,z,0,1,n);
  128.    add3(total,n,total);
  129.    get_quad_normal(x,z,1,0,n);
  130.    add3(total,n,total);
  131.    get_quad_normal(x,z,1,1,n);
  132.    add3(total,n,total);
  133.    normalize(total);
  134.    n[0]=total[0];
  135.    n[1]=total[1];
  136.    n[2]=total[2];
  137. }
  138.  
  139. /*
  140.  * Get a normal to a point as the average
  141.  * of the surrounding quads.
  142.  */
  143.  
  144. void get_vertex_normal(int x, int z, GLdouble n[3])
  145. {
  146.    GLdouble total[3]={0,0,0};
  147.    if((x>0) && (z>0))
  148.     {
  149.      get_quad_normal(x-1,z-1,1,1,n);
  150.      add3(total,n,total);
  151.     }
  152.    if((x>0) && (z<(DIM-1)))
  153.     {
  154.      get_quad_normal(x-1,z,1,0,n);
  155.      add3(total,n,total);
  156.     }
  157.    if((x<(DIM-1)) && (z>0))
  158.     {
  159.      get_quad_normal(x,z-1,0,1,n);
  160.      add3(total,n,total);
  161.     }
  162.    if((x<(DIM-1)) && (z<(DIM-1)))
  163.     {
  164.      get_quad_normal(x,z,0,0,n);
  165.      add3(total,n,total);
  166.     }
  167.    normalize(total);
  168.    n[0]=total[0];
  169.    n[1]=total[1];
  170.    n[2]=total[2];
  171. }
  172.  
  173. /*
  174.  * Draw the scene
  175.  */
  176.  
  177. void draw_scene(int av, int drape, int white)
  178. {
  179.     int xstrip, zrow;
  180.  
  181.     if(drape) {
  182.         glTexImage2D(GL_TEXTURE_2D, 0, 3,
  183.                      DIM, DIM, 0, GL_RGB,
  184.                      GL_UNSIGNED_BYTE, &cols[0][0][0]);
  185.         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  186.         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
  187.         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  188.         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  189.         glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  190.         glEnable(GL_TEXTURE_2D);
  191.     }
  192.     else
  193.         glDisable(GL_TEXTURE_2D);
  194.  
  195.     /*
  196.      * Clear the image buffer.
  197.      */
  198.     if(white)
  199.      glClearColor(1,1,1,1);
  200.     else
  201.      glClearColor(0,0,0,1);
  202.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  203.  
  204.  
  205.     if(drape)
  206.         glColor3ub(255,255,255);    /* basic white surface to be modulated */
  207.     for(xstrip=0;xstrip<DIM-1;xstrip++)
  208.      {
  209.       glBegin(GL_QUADS);
  210.       for(zrow=0;zrow<DIM-1;zrow++)
  211.        {
  212.         GLdouble *c1, *c2, *c3, *c4;
  213.         GLdouble n1[3], n2[3], n3[3], n4[3];
  214.         GLdouble t1[2], t2[2], t3[2], t4[2];
  215.         int passes,toggle;
  216.  
  217.         /* corner co-ords */
  218.         c1 = &mesh[xstrip][zrow][0];
  219.         c2 = &mesh[xstrip+1][zrow][0];
  220.         c3 = &mesh[xstrip+1][zrow+1][0];
  221.         c4 = &mesh[xstrip][zrow+1][0];
  222.  
  223.         /*
  224.          * texture co-ords - these look a bit odd, but we don't want to
  225.          * drape the entire texture over the surface - the vertices are
  226.          * assumed to be the centres of the squares on the texture and thus
  227.          * vertex 0,0 is halfway into the first square of the texture. Thus
  228.          * the texture is DIM wide, but the surface is DIM-1 wide compared
  229.          * to it - hence the +0.5's to offset the surface into the texture.
  230.          */
  231.         t1[1]=(xstrip+0.5)/DIM;    t1[0]=(zrow+0.5)/DIM;
  232.         t2[1]=(xstrip+1.5)/DIM;    t2[0]=(zrow+0.5)/DIM;
  233.         t3[1]=(xstrip+1.5)/DIM;    t3[0]=(zrow+1.5)/DIM;
  234.         t4[1]=(xstrip+0.5)/DIM;    t4[0]=(zrow+1.5)/DIM;
  235.  
  236.         /* normal vectors */
  237.         if(av)
  238.          {
  239.           get_vertex_normal(xstrip,zrow,n1);
  240.           get_vertex_normal(xstrip+1,zrow,n2);
  241.           get_vertex_normal(xstrip+1,zrow+1,n3);
  242.           get_vertex_normal(xstrip,zrow+1,n4);
  243.          }
  244.         else
  245.          {
  246.           get_plane_normal(xstrip,zrow,n1);
  247.           memcpy(n2,n1,3*sizeof(GLdouble));
  248.           memcpy(n3,n1,3*sizeof(GLdouble));
  249.           memcpy(n4,n1,3*sizeof(GLdouble));
  250.          }
  251.  
  252.         /*
  253.          * we do this to draw the quads in the opposite direction for
  254.          * each strip as this reduces the effects of the triangluarisation
  255.          * of the quad by the rendering algorithm.
  256.          */
  257.         for(passes=0;passes<4;passes++)
  258.          {
  259.          if((xstrip&1) == (zrow&1))
  260.           toggle=3-passes;
  261.          else
  262.           toggle=passes;
  263.          switch (toggle)
  264.           {
  265.           case 0:
  266.            glNormal3dv(n1);
  267.            if(drape)
  268.                glTexCoord2dv(t1);
  269.            else
  270.                glColor3ubv(&cols[xstrip][zrow][0]);
  271.            glVertex3dv(c1);
  272.            break;
  273.  
  274.           case 1:
  275.            glNormal3dv(n2);
  276.            if(drape)
  277.                glTexCoord2dv(t2);
  278.            else
  279.                glColor3ubv(&cols[xstrip+1][zrow][0]);
  280.            glVertex3dv(c2);
  281.            break;
  282.  
  283.           case 2:
  284.            glNormal3dv(n3);
  285.            if(drape)
  286.                glTexCoord2dv(t3);
  287.            else
  288.                glColor3ubv(&cols[xstrip+1][zrow+1][0]);
  289.            glVertex3dv(c3);
  290.            break;
  291.    
  292.           case 3:
  293.            glNormal3dv(n4);
  294.            if(drape)
  295.                glTexCoord2dv(t4);
  296.            else
  297.                glColor3ubv(&cols[xstrip][zrow+1][0]);
  298.            glVertex3dv(c4);
  299.            break;
  300.           }
  301.          }
  302.        }
  303.       glEnd();
  304.      }
  305.  
  306.     glFlush();
  307. }
  308.  
  309. /*
  310.  * We use the display postscript operators to send
  311.  * an outline of the base area directly into the window
  312.  * by projecting points and drawing lines. We also draw
  313.  * a small arrow representing "north" to hep orientation.
  314.  */
  315.  
  316. void outline_scene(void)
  317. {
  318.     GLdouble model[16], proj[16];
  319.     GLint viewport[4];
  320.     GLdouble winx, winy, winz;
  321.  
  322.     glGetDoublev(GL_MODELVIEW_MATRIX, model);
  323.     glGetDoublev(GL_PROJECTION_MATRIX, proj);
  324.     glGetIntegerv(GL_VIEWPORT, viewport);
  325.  
  326.     /* Having got these we can draw the base */
  327.     PSnewpath();
  328.     gluProject(-50.0, 0, -50.0, model, proj, viewport, &winx, &winy, &winz);
  329.     PSmoveto(winx,winy);
  330.     gluProject(50.0, 0, -50.0, model, proj, viewport, &winx, &winy, &winz);
  331.     PSlineto(winx,winy);
  332.     gluProject(50.0, 0, 50.0, model, proj, viewport, &winx, &winy, &winz);
  333.     PSlineto(winx,winy);
  334.     gluProject(-50.0, 0, 50.0, model, proj, viewport, &winx, &winy, &winz);
  335.     PSlineto(winx,winy);
  336.     PSclosepath();
  337.     PSstroke();
  338.  
  339.     /* draw the "north" arrow */
  340.     PSnewpath();
  341.     gluProject(-10.0, 0, 0.0, model, proj, viewport, &winx, &winy, &winz);
  342.     PSmoveto(winx,winy);
  343.     gluProject(10.0, 0, 0.0, model, proj, viewport, &winx, &winy, &winz);
  344.     PSlineto(winx,winy);
  345.     gluProject(0.0, 0, 10.0, model, proj, viewport, &winx, &winy, &winz);
  346.     PSmoveto(winx,winy);
  347.     gluProject(0.0, 0, -15.0, model, proj, viewport, &winx, &winy, &winz);
  348.     PSlineto(winx,winy);
  349.     gluProject(-5.0, 0, -10.0, model, proj, viewport, &winx, &winy, &winz);
  350.     PSmoveto(winx,winy);
  351.     gluProject(0.0, 0, -15.0, model, proj, viewport, &winx, &winy, &winz);
  352.     PSlineto(winx,winy);
  353.     gluProject(5.0, 0, -10.0, model, proj, viewport, &winx, &winy, &winz);
  354.     PSlineto(winx,winy);
  355.     PSstroke();
  356. }
  357.